package com.jy.oms.framework.asyn.task.executor.filter;

import com.jy.oms.framework.asyn.task.alarm.AlarmMessage;
import com.jy.oms.framework.asyn.task.alarm.AlarmMessageFacade;
import com.jy.oms.framework.asyn.task.cluster.config.ITaskConfigChangeListener;
import com.jy.oms.framework.asyn.task.cluster.config.ITaskConfigService;
import com.jy.oms.framework.asyn.task.handler.ITaskHandlerProcessor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 任务黑白名单校验
 *
 * @author liuquan
 */
public abstract class AbstractTaskBlackWhitelistFilter implements ITaskHandlerProcessor {
    protected static Logger logger = LoggerFactory.getLogger(AbstractTaskBlackWhitelistFilter.class);

    @Autowired
    private ITaskConfigService configService;
    private List<String> blacklist;
    private List<String> whitelist;
    private volatile boolean isBlackAlarmOnConfigChange;
    private volatile boolean isWhiteAlarmOnConfigChange;

    @Override
    public void processAfterTaskHandlerInitialization() {
        this.listenConfigKeyChange(true);
        this.listenConfigKeyChange(false);
    }

    private void listenConfigKeyChange(boolean isWhitelist) {
        configService.addTaskConfigChangeListener(new ITaskConfigChangeListener() {
            @Override
            public String getConfigKey() {
                return isWhitelist ? getWhitelistConfigKey() : getBlacklistConfigKey();
            }

            @Override
            public void onConfigChange(String configKey, String config) {
                List<String> taskCodes = parseTaskConfig(config);
                if (isWhitelist) {
                    whitelist = taskCodes;

                    //初始化时不告警
                    if (isWhiteAlarmOnConfigChange) {
                        alarm(isWhitelist, taskCodes);
                    }else{
                        isWhiteAlarmOnConfigChange = true;
                    }
                } else {
                    blacklist = taskCodes;

                    //初始化时不告警
                    if (isBlackAlarmOnConfigChange) {
                        alarm(isWhitelist, taskCodes);
                    }else{
                        isBlackAlarmOnConfigChange = true;
                    }
                }
            }
        });
    }

    private void alarm(boolean isWhitelist, List<String> taskCodes) {
        if (CollectionUtils.isEmpty(taskCodes)) {
            return;
        }

        AlarmMessage alarmMessage = AlarmMessage.create()
                .title(this.getAlarmTitle())
                .add(isWhitelist ? "白名单" : "黑名单", isWhitelist ? "只有指定任务可以执行" : "指定任务不能执行")
                .add("任务编码", taskCodes.stream().collect(Collectors.joining(",")));
        AlarmMessageFacade.getInstance().alarm(alarmMessage);
    }

    private List<String> parseTaskConfig(String config) {
        if (StringUtils.isBlank(config)) {
            return null;
        }

        return Arrays.stream(config.split(","))
                .filter(e -> StringUtils.isNotBlank(e))
                .map(e -> StringUtils.trim(e))
                .collect(Collectors.toList());
    }

    /**
     * 黑名单配置key
     */
    protected abstract String getBlacklistConfigKey();

    /**
     * 白名单配置key
     */
    protected abstract String getWhitelistConfigKey();

    protected abstract String getAlarmTitle();

    /**
     * 判断是否禁用所有任务
     */
    protected boolean judgeDisableAllTask(){
        if (CollectionUtils.isNotEmpty(blacklist)) {
            String disableAllTask = blacklist.get(0);
            if (disableAllTask.equals("*")) {
                //所有任务不能执行
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否可以运行任务
     *
     * @param code 配置编码
     */
    protected boolean judgeAbleRunTask(String code) {
        //黑名单任务不允许执行
        if (CollectionUtils.isNotEmpty(blacklist)) {
            boolean disableAllTask = this.judgeDisableAllTask();
            if(disableAllTask){
                return false;
            }

            if (blacklist.contains(code)) {
                return false;
            }
        }

        //只有白名单任务允许执行
        if (CollectionUtils.isNotEmpty(whitelist)) {
            if (!whitelist.contains(code)) {
                return false;
            }
        }

        return true;
    }

    public List<String> getBlacklist() {
        return blacklist;
    }

    public List<String> getWhitelist() {
        return whitelist;
    }
}
